package simbot.example.util;
 
import lombok.extern.slf4j.Slf4j;
import love.forte.simbot.resources.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
 
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;

/**
 * @author ：lixinyu
 * @version ：M1.0
 * @program ：vevor-research
 * @date ：Created in 2020/9/11 9:59
 * @description ：java图片处理类，包括java图片处理,java图片水印,java图片切割,java图片缩放,java图片格式转换,java图片等比例缩小
 *                Image是一个抽象类，BufferedImage是其实现类，是一个带缓冲区图像类，主要作用是将一幅图片加载到内存中
 *               （BufferedImage生成的图片在内存里有一个图像缓冲区，利用这个缓冲区我们可以很方便地操作这个图片），
 *                提供获得绘图对象、图像缩放、选择图像平滑度等功能，通常用来做图片大小变换、图片变灰、设置透明不透明等。
 */
@Slf4j
public class ImageServiceImpl {

    /**
     * 给图片添加图片水印
     * @param pressImg       水印图片
     * @param localImagePath 源图像地址
     * @param pressImageFile 目标图像地址
     * @param x              修正值。 默认在中间
     * @param y              修正值。 默认在中间
     * @param alpha          透明度,必须是范围 [0.0, 1.0] 之内（包含边界值）的一个浮点数字,值越小透明度越高
     * @throws IOException   IOException
     */
    public static void imageWatermark(String pressImg, String localImagePath, String pressImageFile, int x, int y, float alpha,int with,int high) throws IOException {
        //源文件
        File localFile = new File(localImagePath);
        if (ObjectUtils.isEmpty(localFile)){
            throw new IllegalArgumentException("未找到图片");
        }
        Image localImage = ImageIO.read(localFile);
        int width = localImage.getWidth(null);
        int height = localImage.getHeight(null);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();
        graphics.drawImage(localImage, 0, 0, width, height, null);


        // 水印文件
        BufferedImage pressImg1 = ImageIO.read(new URL(pressImg));
        BufferedImage bufferedImage1 = scaleByPercentage(pressImg1, with, high);
        BufferedImage bufferedImage = cutHeadImages(bufferedImage1);
        int markImageWidth = bufferedImage.getWidth(null);
        int markImageHeight = bufferedImage.getHeight(null);
        // 将新像素与图形处理器上的现有像素组合
        graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 矩形图像原点为左上角,x,y=0,图片水印在源图中间
        // x为原点在水平距离向右的修正值，x为原点在垂直距离向下的修正值
        graphics.drawImage(bufferedImage, x, y, markImageWidth, markImageHeight, null);
        // 释放图形处理资源
        graphics.dispose();
        ImageIO.write(image,  "jpg", new File(pressImageFile));
    }

    //将图片变为圆
    public static BufferedImage cutHeadImages(BufferedImage avatarImage) {
        try {
            int width = avatarImage.getWidth();
            // 透明底的图片
            BufferedImage formatAvatarImage = new BufferedImage(width, width, BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D graphics = formatAvatarImage.createGraphics();
            //把图片切成一个园
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            //留一个像素的空白区域，这个很重要，画圆的时候把这个覆盖
            int border = 1;
            //图片是一个圆型
            Ellipse2D.Double shape = new Ellipse2D.Double(border, border, width - border * 2, width - border * 2);
            //需要保留的区域
            graphics.setClip(shape);
            graphics.drawImage(avatarImage, border, border, width - border * 2, width - border * 2, null);
            graphics.dispose();
            //在圆图外面再画一个圆
            //新创建一个graphics，这样画的圆不会有锯齿
            graphics = formatAvatarImage.createGraphics();
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            int border1 = 3;
            //画笔是4.5个像素，BasicStroke的使用可以查看下面的参考文档
            //使画笔时基本会像外延伸一定像素，具体可以自己使用的时候测试
            Stroke s = new BasicStroke(5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            graphics.setStroke(s);
            graphics.setColor(Color.WHITE);
            graphics.drawOval(border1, border1, width - border1 * 2, width - border1 * 2);
            graphics.dispose();
            return formatAvatarImage;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 缩小Image，此方法返回源图像按给定宽度、高度限制下缩放后的图像
     *
     * @param inputImage
     *            ：压缩后宽度
     *            ：压缩后高度
     * @throws java.io.IOException
     *             return
     */
    public static BufferedImage scaleByPercentage(BufferedImage inputImage, int newWidth, int newHeight){
        // 获取原始图像透明度类型
        try {
            int type = inputImage.getColorModel().getTransparency();
            int width = inputImage.getWidth();
            int height = inputImage.getHeight();
            // 开启抗锯齿
            RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 使用高质量压缩
            renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            BufferedImage img = new BufferedImage(newWidth, newHeight, type);
            Graphics2D graphics2d = img.createGraphics();
            graphics2d.setRenderingHints(renderingHints);
            graphics2d.drawImage(inputImage, 0, 0, newWidth, newHeight, 0, 0, width, height, null);
            graphics2d.dispose();
            return img;

        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
 